package org.javahispano.javacup.tacticas_aceptadas.PeterEvans.TheGuarrosFromSwaziland.net.pedroferrera.javacup.helpers;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.javahispano.javacup.tacticas_aceptadas.PeterEvans.TheGuarrosFromSwaziland.net.pedroferrera.javacup.core.JavacupHelper;
import org.javahispano.javacup.tacticas_aceptadas.PeterEvans.TheGuarrosFromSwaziland.net.pedroferrera.javacup.core.Utils;

import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;

/**
 * 
 * @author Peter Evans
 *
 */
public class InterceptorLibreHelper extends JavacupHelper<List<Comando>> {

	protected List<Posicion> historyPelota = new LinkedList<Posicion>();
	
	public final static int MAX_HISTORY = 5;
	
	protected double distance;
	protected boolean irSiParado = false;
	protected int cupo = 11;
	
	public InterceptorLibreHelper(double distance, int cupo, boolean irSiParado) {
		this.distance = distance;
		this.cupo = cupo;
		this.irSiParado = irSiParado;
	}
	
	@Override
	public List<Comando> help(SituacionPartido sp, int... jugadores) {
		List<Comando> comandoList = new ArrayList<Comando>();				
		if(sp.balon().getX() == 0 && sp.balon().getY() == 0) {
			return null;
		}
		if(historyPelota.size() == MAX_HISTORY) {
			historyPelota.remove(0);
			historyPelota.add(sp.balon());
		} else {
			historyPelota.add(sp.balon());
			return null;
		}
		double a = 0;
		double b = 0;
		Posicion ref = null;
		boolean ySign = false;
		boolean xSign = false;
		double avgChange = 0;
		for(Posicion p: historyPelota) {
			if(ref != null) {
				avgChange += Math.abs(ref.getX() - p.getX());
				avgChange += Math.abs(ref.getY() - p.getY());
				if(p.getY() > ref.getY()) {
					ySign = true; // y grows
				} else {
					ySign = false; // y decreases
				}
				if(p.getX() > ref.getX()) {
					xSign = true; // x grows
				} else {
					xSign = false; // x decreases
				}
				// a = (y-y')/(x-x')
				a += (p.getY() - ref.getY()) / (p.getX() - ref.getX());
			}
			ref = p;
		}
		avgChange = avgChange / (double)(historyPelota.size() - 1);
		if(a >= Double.MAX_VALUE) {
			return comandoList;
		}
		a = a / (double)(historyPelota.size() - 1);
		// b = y' - ax
		// y = b + ax
		b = ref.getY() - a*ref.getX();
		final int cupo = 3;
		int selected = 0;
		for(int i: jugadores) {
			Posicion thisPos = sp.misJugadores()[i];
			if(thisPos.distancia(sp.balon()) < distance) {
				selected++;
				if(selected == cupo) {
					continue;
				}
				if(avgChange < 1 && irSiParado) {
					comandoList.add(new ComandoIrA(i, sp.balon()));
					continue;
				}

				Posicion objective = new Posicion((thisPos.getY() - b) / a, thisPos.getY());
				Posicion objective2 = new Posicion(thisPos.getX(), thisPos.getX()*a + b);
								
				Posicion chosen = null;
				boolean objectivePossible = true;
				boolean objective2Possible = true;
				
				if(thisPos.getY() < (Constantes.centroArcoInf.getY()+2)) {
					objective2Possible = false;
				}

				if(ySign && (objective.getY() < thisPos.getY())) {
					objectivePossible = false;
				}
				if(!ySign && (objective.getY() > thisPos.getY())) {
					objectivePossible = false;
				}
				if(xSign && (objective.getX() < thisPos.getX())) {
					objectivePossible = false;
				}
				if(!xSign && (objective.getX() > thisPos.getX())) {
					objectivePossible = false;
				}		
				if(ySign && (objective2.getY() < thisPos.getY())) {
					objective2Possible = false;
				}
				if(!ySign && (objective2.getY() > thisPos.getY())) {
					objective2Possible = false;
				}
				if(xSign && (objective2.getX() < thisPos.getX())) {
					objective2Possible = false;
				}
				if(!xSign && (objective2.getX() > thisPos.getX())) {
					objective2Possible = false;
				}		
				if(!Utils.dentro(objective)) {
					objectivePossible = false;
				}
				if(!Utils.dentro(objective2)) {
					objective2Possible = false;
				}
				if(objectivePossible && objective2Possible) {
					if(sp.balon().distancia(objective) < sp.balon().distancia(objective2)) {
						chosen = objective;
					} else {
						chosen = objective2;
					}
				} else if(objectivePossible) {
					chosen = objective;
				} else if(objective2Possible) {
					chosen = objective2;
				}
				if(chosen != null) {
					comandoList.add(new ComandoIrA(i, chosen));
				}
			}
		}
		return comandoList;
	}
	
	public double getDistance() {
		return distance;
	}

	public void setDistance(double distance) {
		this.distance = distance;
	}

	public static void main(String[] args) {
		
	}
}
